home *** CD-ROM | disk | FTP | other *** search
- /*
- * (c)Copyright 1992-1997 Obvious Implementations Corp. Redistribution and
- * use is allowed under the terms of the DICE-LICENSE FILE,
- * DICE-LICENSE.TXT.
- */
-
- /*
- * GENMISC.C
- *
- * Miscellanious stuff and some of the more esoteric generation routines
- * such as -> . &lvalue [], etc...
- */
-
- #include "defs.h"
-
- Prototype void GenCast(Exp **);
- Prototype void GenSizeof(Exp **);
- Prototype void GenAddr(Exp **);
- Prototype void GenInd(Exp **);
- Prototype void GenPreInc(Exp **);
- Prototype void GenPreDec(Exp **);
- Prototype void GenIntConst(Exp **);
- Prototype void GenStrConst(Exp **);
- Prototype void GenFltConst(Exp **);
- Prototype void GenVarRef(Exp **);
- Prototype void GenCall(Exp **);
- Prototype void GenCastArgs(Type *, Exp *, Exp **);
- Prototype void GenPosInc(Exp **);
- Prototype void GenPosDec(Exp **);
- Prototype void GenStructInd(Exp **);
- Prototype void GenStructElm(Exp **);
- Prototype void GenArray(Exp **);
- Prototype void GenBFExt(Exp **);
- Prototype void BitFieldResultExp(Exp *);
- Prototype void BitFieldResultType(Exp **, int);
-
- Local void GenRegArgs(Exp *, char *, char *, ulong, char *, short);
- Local void SaveCopyConflictsRegArgs(Exp *, char *, char *, ulong, short);
- Local void FreeRegArgs(Exp *, char *);
- Local long GenPushArgs(Exp *);
- Local int PushArgExp(Exp *);
- Local void InMaskPush(Exp *, char *);
- Local void InMaskPop(char *);
-
- /*
- * GenCast()
- */
-
- void
- GenCast(pexp)
- Exp **pexp;
- {
- Exp *exp = *pexp; /* left side exp, right side type */
- Exp *e1;
-
- Assert(exp->ex_Type);
- if (GenPass == 0) {
- if ((exp->ex_Flags & EF_ICAST) == 0) { /* see insert cast */
- if (exp->ex_ExpL->ex_Type == NULL)
- exp->ex_ExpL->ex_Type = exp->ex_Type; /* optimize */
- CallLeft();
- }
- e1 = exp->ex_ExpL;
-
- if (e1->ex_Stor.st_Type == ST_IntConst) {
- e1->ex_Type = exp->ex_Type;
- e1->ex_Stor.st_Size = e1->ex_Type->Size;
-
- if (exp->ex_Type->Id == TID_FLT) {
- e1->ex_Stor.st_FltConst = IntToFPStr(e1->ex_Stor.st_IntConst, e1->ex_Stor.st_Flags & SF_UNSIGNED, &e1->ex_Stor.st_FltLen);
- e1->ex_Type = exp->ex_Type;
- e1->ex_Stor.st_Size = e1->ex_Type->Size;
- e1->ex_Stor.st_Type = ST_FltConst;
- e1->ex_Token = TokFltConst;
- e1->ex_Func = GenFltConst;
- *pexp = e1;
- return;
- }
-
- if (e1->ex_Type->Flags & TF_UNSIGNED) {
- switch(e1->ex_Type->Size) {
- case 0:
- e1->ex_Stor.st_UIntConst = 0;
- break;
- case 1:
- e1->ex_Stor.st_UIntConst = (ubyte)e1->ex_Stor.st_UIntConst;
- break;
- case 2:
- e1->ex_Stor.st_UIntConst = (uword)e1->ex_Stor.st_UIntConst;
- break;
- case 4:
- break;
- default:
- Assert(0);
- }
- e1->ex_Stor.st_Flags |= SF_UNSIGNED;
- } else {
- switch(e1->ex_Type->Size) {
- case 0:
- e1->ex_Stor.st_IntConst = 0;
- break;
- case 1:
- e1->ex_Stor.st_IntConst = (char)e1->ex_Stor.st_IntConst;
- break;
- case 2:
- e1->ex_Stor.st_IntConst = (short)e1->ex_Stor.st_IntConst;
- break;
- case 4:
- break;
- default:
- yerror(exp->ex_LexIdx, EERROR_ILLEGAL_CAST);
- break;
- }
- e1->ex_Stor.st_Flags &= ~SF_UNSIGNED;
- }
- *pexp = e1;
- return;
- }
-
- /*
- * Floating constant to integer
- *
- * e1->ex_StrConst e1->ex_StrLen
- */
-
- if (e1->ex_Stor.st_Type == ST_FltConst) {
- if (exp->ex_Type->Id == TID_FLT) { /* flt->flt no change */
- *pexp = e1;
- e1->ex_Type = exp->ex_Type;
- return;
- }
- if (exp->ex_Type->Id == TID_INT) {
- e1->ex_Stor.st_IntConst = FPStrToInt(e1, e1->ex_Stor.st_FltConst, e1->ex_Stor.st_FltLen);
- e1->ex_Type = exp->ex_Type;
- e1->ex_Stor.st_Size = e1->ex_Type->Size;
- e1->ex_Stor.st_Type = ST_IntConst;
- e1->ex_Token = TokIntConst;
- e1->ex_Func = GenIntConst;
- if (e1->ex_Stor.st_Size == 0) /* cast to void */
- e1->ex_Stor.st_IntConst = 0;
- *pexp = e1;
-
- if (exp->ex_Type->Flags & TF_UNSIGNED)
- exp->ex_Stor.st_Flags |= SF_UNSIGNED;
- else
- exp->ex_Stor.st_Flags &= ~SF_UNSIGNED;
-
- return;
- }
- }
-
- /*
- * If Flt->Flt, Flt->Int, or Int->Flt conversion then
- * set EF_CALL bit. (doesn't handle void case here)
- */
-
- if (exp->ex_Type->Id == TID_FLT || e1->ex_Type->Id == TID_FLT) {
- exp->ex_Flags |= EF_CALL;
- GenFlagCallMade();
- }
- exp->ex_Flags |= e1->ex_Flags & EF_CALL;
- } else {
- Type *t = exp->ex_Type;
-
- e1 = exp->ex_ExpL;
-
- if (exp->ex_Flags & EF_RNU) {
- e1->ex_Flags |= EF_RNU;
- CallLeft();
- return;
- }
-
- if (e1->ex_Type->Id == TID_ARY) {
- CallLeft();
- if (exp->ex_Flags & (EF_PRES|EF_ASSEQ)) {
- CreateUnaryResultStorage(exp, 1);
- asm_lea(exp, &e1->ex_Stor, 0, &exp->ex_Stor);
- } else {
- FreeStorage(&e1->ex_Stor);
- /* X1 */
- asm_getlea(exp, &e1->ex_Stor, &exp->ex_Stor);
- }
- return;
- }
-
- /*
- * Floating point conversions fp -> int, int -> fp
- */
-
- if (exp->ex_Type->Id == TID_FLT || e1->ex_Type->Id == TID_FLT) {
- CallLeft();
- CreateUnaryResultStorage(exp, 1);
-
- if (exp->ex_Type->Id == TID_FLT) {
- if (e1->ex_Type->Id == TID_FLT) { /* FLT -> FLT */
- asm_fptofp(exp, &e1->ex_Stor, &exp->ex_Stor);
- } else { /* INT -> FLT */
- asm_inttofp(exp, &e1->ex_Stor, &exp->ex_Stor);
- }
- } else { /* FLT -> INT (if not cast to void) */
- if (exp->ex_Stor.st_Size)
- asm_fptoint(exp, &e1->ex_Stor, &exp->ex_Stor);
- }
-
- if (exp->ex_Type->Flags & TF_UNSIGNED)
- exp->ex_Stor.st_Flags |= SF_UNSIGNED;
- else
- exp->ex_Stor.st_Flags &= ~SF_UNSIGNED;
-
- return;
- }
-
- /*
- * Bitfield Conversions
- *
- * XXX Enabled 23 Dec 95, Matt Dillon, to handle case where
- * bitfield assignment occurs within expression and then must
- * be extracted out again.
- */
-
- if (exp->ex_Type->Id == TID_INT && e1->ex_Type->Id == TID_BITFIELD) {
- CallLeft();
- CreateUnaryResultStorage(exp, 1);
-
- if (t->Flags & TF_UNSIGNED)
- exp->ex_Stor.st_Flags |= SF_UNSIGNED;
- else
- exp->ex_Stor.st_Flags &= ~SF_UNSIGNED;
-
- asm_bfext(exp, &e1->ex_Stor, &exp->ex_Stor);
-
- return;
- }
-
- if ((exp->ex_Flags & (EF_PRES|EF_ASSEQ)) == 0) {
- if (t->Size == e1->ex_Type->Size) {
- CallLeft();
- FreeStorage(&e1->ex_Stor);
- ReuseStorage(&e1->ex_Stor, &exp->ex_Stor);
-
- if (t->Flags & TF_UNSIGNED)
- exp->ex_Stor.st_Flags |= SF_UNSIGNED;
- else
- exp->ex_Stor.st_Flags &= ~SF_UNSIGNED;
-
- return;
- }
- }
-
- /*
- * If storage size is the same & storage passed down from parent
- * then pass to subexp.
- */
-
- if (t->Size == e1->ex_Type->Size && (exp->ex_Flags & EF_PRES) && (e1->ex_Flags & (EF_CRES|EF_ASSEQ)) == 0) {
- e1->ex_Flags |= EF_PRES;
- e1->ex_Stor = exp->ex_Stor;
-
- if (e1->ex_Type->Flags & TF_UNSIGNED) /* ??? XXX */
- e1->ex_Stor.st_Flags |= SF_UNSIGNED;
- else
- e1->ex_Stor.st_Flags &= ~SF_UNSIGNED;
-
- CallLeft();
- return;
- }
-
- CallLeft();
-
- CreateUnaryResultStorage(exp, 1);
-
- if (t->Flags & TF_UNSIGNED)
- exp->ex_Stor.st_Flags |= SF_UNSIGNED;
- else
- exp->ex_Stor.st_Flags &= ~SF_UNSIGNED;
-
- if (exp->ex_Stor.st_Size)
- asm_ext(exp, &e1->ex_Stor, &exp->ex_Stor, e1->ex_Stor.st_Flags);
- }
- }
-
- /*
- * Strings use a dummy CharAryType ... not a real type because its size does
- * not match the size of the string. So we hack the only operator that will
- * ever need the size.
- */
-
- void
- GenSizeof(pexp)
- Exp **pexp;
- {
- Exp *exp = *pexp;
- Type *type;
- long size;
-
- if (GenPass == 0) {
- if (exp->ex_ExpL) {
- Exp *e1;
-
- CallLeft();
- e1 = exp->ex_ExpL;
-
- type = e1->ex_Type;
- size = type->Size;
-
- if (e1->ex_Stor.st_Type == ST_StrConst) {
- DelStrList(e1->ex_Stor.st_Label);
- size = e1->ex_Stor.st_StrLen;
- }
- } else {
- type = exp->ex_Type;
- size = type->Size;
- if (size == 0)
- {
- if ((type->Id == TID_STRUCT) || (type->Id == TID_UNION))
- Undefined_Tag(type, NULL, exp->ex_LexIdx);
- else
- yerror(exp->ex_LexIdx, EERROR_SIZEOF_TYPE_0);
- }
- }
- exp->ex_ExpL = NULL;
- AllocConstStor(&exp->ex_Stor, size, &LongType);
- exp->ex_Type = &LongType;
- exp->ex_Stor.st_Flags |= SF_NOSA;
- exp->ex_Func = GenIntConst;
- exp->ex_Flags |= EF_CRES;
- }
- }
-
- void
- GenAddr(pexp)
- Exp **pexp;
- {
- Exp *exp = *pexp;
- Exp *e1;
-
- CallLeft();
- e1 = exp->ex_ExpL;
-
- if (GenPass == 0) {
- exp->ex_Flags |= e1->ex_Flags & EF_CALL;
- if (e1->ex_Token == TokVarRef)
- e1->ex_Var->Flags |= VF_ADDR;
-
- #ifdef NOTDEF
- if (e1->ex_Type->Id == TID_ARY) {
- if (e1->ex_Stor.st_Type != ST_IntConst) /* no warning for offsetof() */
- yerror(e1->ex_LexIdx, EWARN_ADDR_ARRAY_REDUNDANT);
- exp->ex_Type = e1->ex_Type;
- } else
- #endif
- if (e1->ex_Type->Id == TID_BITFIELD) {
- yerror(e1->ex_LexIdx, EERROR_ADDR_BITFIELD_ILLEGAL);
- } else {
- exp->ex_Type = TypeToPtrType(e1->ex_Type);
- }
- exp->ex_Flags |= EF_CRES;
-
- /*
- * handle address of constant pointer, make it handlable as a
- * constant expression.
- */
-
- if (e1->ex_Stor.st_Type == ST_PtrConst) {
- asm_getlea(exp, &e1->ex_Stor, &exp->ex_Stor);
- #ifdef NOTDEF
- exp->ex_Stor.st_Type = ST_IntConst;
- exp->ex_Stor.st_IntConst = e1->ex_Stor.st_PtrConst;
- #endif
- exp->ex_Stor.st_Flags |= SF_NOSA;
- exp->ex_Func = GenIntConst;
- exp->ex_Flags |= EF_CRES;
- if (exp->ex_Type->Id == TID_ARY)
- exp->ex_Stor.st_Flags |= SF_LEA;
- } else if (e1->ex_Stor.st_Type == ST_IntConst) {
- exp->ex_Stor = e1->ex_Stor;
- exp->ex_Stor.st_Flags &= ~SF_LEA;
- }
- } else {
- if ((exp->ex_Flags & EF_RNU) == 0) {
- if (e1->ex_Type->Id == TID_ARY) {
- exp->ex_Stor = e1->ex_Stor;
- } else {
- FreeStorage(&e1->ex_Stor);
- asm_getlea(exp, &e1->ex_Stor, &exp->ex_Stor);
- }
- } else {
- FreeStorage(&e1->ex_Stor);
- }
- }
- }
-
- void
- GenInd(pexp)
- Exp **pexp;
- {
- Exp *exp = *pexp;
- Exp *e1;
-
- CallLeft();
- e1 = exp->ex_ExpL;
-
- if (GenPass == 0) {
- exp->ex_Type = e1->ex_Type;
- exp->ex_Flags |= e1->ex_Flags & EF_CALL;
-
- if (exp->ex_Type->Id != TID_PTR && exp->ex_Type->Id != TID_ARY) {
- yerror(exp->ex_LexIdx, EERROR_INDIRECTION_NOT_PTR);
- return;
- }
- exp->ex_Type = e1->ex_Type->SubType;
- /*exp->ex_Flags |= EF_CRES;*/
- } else {
- FreeStorage(&e1->ex_Stor);
- if ((exp->ex_Flags & EF_RNU) == 0) {
- asm_getind(exp, e1->ex_Type, &e1->ex_Stor, &exp->ex_Stor, -1, -1, AutoResultStorage(exp));
- }
- return;
- }
- }
-
- void
- GenPreInc(pexp)
- Exp **pexp;
- {
- Exp *exp = *pexp;
- Exp *e1;
-
- CallLeft();
- e1 = exp->ex_ExpL;
-
- if (GenPass == 0) {
- #ifdef NOTDEF
- if (e1->ex_Stor.st_Type == ST_IntConst) {
- e1->ex_Stor.st_IntConst = !e1->ex_Stor.st_IntConst;
- e1->ex_Type = &LongType;
- *pexp = e1;
- return;
- }
- #endif
- exp->ex_Type = e1->ex_Type;
- exp->ex_Flags |= e1->ex_Flags & EF_CALL;
- exp->ex_Flags |= EF_CRES;
-
- if (e1->ex_Token == TokVarRef)
- e1->ex_Var->RegFlags |= RF_MODIFIED;
- if (e1->ex_Type->Id == TID_FLT) {
- exp->ex_Flags |= EF_CALL;
- GenFlagCallMade();
- }
- } else {
- Stor con;
-
- if (exp->ex_Type->Id == TID_FLT) {
- AllocFltConstStor(&con, "1", 1, exp->ex_Type);
- asm_fpadd(exp, exp->ex_Type, &con, &e1->ex_Stor, &e1->ex_Stor);
- } else {
- AllocConstStor(&con, AutoIncDecSize(e1), e1->ex_Type);
- asm_add(exp, &con, &e1->ex_Stor, &e1->ex_Stor);
- }
- FreeStorage(&e1->ex_Stor);
-
- if ((exp->ex_Flags & EF_RNU) == 0)
- ReuseStorage(&e1->ex_Stor, &exp->ex_Stor);
- }
- }
-
- void
- GenPreDec(pexp)
- Exp **pexp;
- {
- Exp *exp = *pexp;
- Exp *e1;
-
- CallLeft();
- e1 = exp->ex_ExpL;
-
- if (GenPass == 0) {
- #ifdef NOTDEF
- if (e1->ex_Stor.st_Type == ST_IntConst) {
- e1->ex_Stor.st_IntConst = !e1->ex_Stor.st_IntConst;
- e1->ex_Type = &LongType;
- *pexp = e1;
- return;
- }
- #endif
- exp->ex_Type = e1->ex_Type;
- exp->ex_Flags |= e1->ex_Flags & EF_CALL;
- exp->ex_Flags |= EF_CRES;
-
- if (e1->ex_Token == TokVarRef)
- e1->ex_Var->RegFlags |= RF_MODIFIED;
- if (e1->ex_Type->Id == TID_FLT) {
- exp->ex_Flags |= EF_CALL;
- GenFlagCallMade();
- }
- } else {
- Stor con;
-
- if (exp->ex_Type->Id == TID_FLT) {
- AllocFltConstStor(&con, "1", 1, exp->ex_Type);
- asm_fpsub(exp, exp->ex_Type, &e1->ex_Stor, &con, &e1->ex_Stor);
- } else {
- AllocConstStor(&con, AutoIncDecSize(e1), e1->ex_Type);
- asm_sub(exp, &e1->ex_Stor, &con, &e1->ex_Stor);
- }
- FreeStorage(&e1->ex_Stor);
-
- if ((exp->ex_Flags & EF_RNU) == 0)
- ReuseStorage(&e1->ex_Stor, &exp->ex_Stor);
- }
- }
-
- /*
- * GenIntConst()
- */
-
- void
- GenIntConst(pexp)
- Exp **pexp;
- {
- Exp *exp = *pexp;
-
- if (GenPass == 0) {
- Type *type;
- long value = exp->ex_Stor.st_IntConst;
-
- if (exp->ex_Stor.st_Flags & SF_UNSIGNED) {
- type = &ULongType;
-
- if ((unsigned long)value < 65536)
- type = &UShortType;
- if ((unsigned long)value < 256)
- type = &UCharType;
- } else {
- type = &LongType;
-
- if (value >= -32768 && value < 32768)
- type = &ShortType;
- if (value >= -128 && value < 128)
- type = &CharType;
- }
-
-
- exp->ex_Type = type;
- exp->ex_Flags |= EF_CRES;
- AllocConstStor(&exp->ex_Stor, value, type);
- } else {
- exp->ex_Stor.st_Size = exp->ex_Type->Size;
-
- if (exp->ex_Flags & EF_COND) {
- exp->ex_Flags |= EF_CONDACK;
- if (exp->ex_Cond >= 0 && exp->ex_Stor.st_IntConst)
- asm_branch(exp->ex_LabelT);
- if (exp->ex_Cond < 0 && !exp->ex_Stor.st_IntConst)
- asm_branch(exp->ex_LabelF);
- }
- if (exp->ex_Type->Flags & TF_UNSIGNED)
- exp->ex_Stor.st_Flags |= SF_UNSIGNED;
- else
- exp->ex_Stor.st_Flags &= ~SF_UNSIGNED;
- }
- }
-
- void
- GenStrConst(pexp)
- Exp **pexp;
- {
- Exp *exp = *pexp;
- long l;
-
- if (GenPass == 0) {
- long iidx = -1; /* internationalization index */
- l = AllocLabel();
-
- exp->ex_Flags |= EF_CRES;
-
- #ifdef COMMERCIAL
- iidx = Internationalize(exp->ex_StrConst, exp->ex_StrLen);
- #endif
- AddStrList(exp->ex_StrConst, exp->ex_StrLen, l, iidx);
- #ifdef COMMERCIAL
- if (iidx >= 0) {
- l = -l;
- exp->ex_Type = &CharPtrType;
- } else
- #endif
- {
- exp->ex_Type = &CharAryType;
- }
-
- exp->ex_Stor.st_StrConst = exp->ex_StrConst;
- exp->ex_Stor.st_StrLen = exp->ex_StrLen;
- exp->ex_Stor.st_Type = ST_StrConst;
- exp->ex_Stor.st_Flags = SF_NOSA;
- exp->ex_Stor.st_Label = l;
- } else {
- #ifdef COMMERCIAL
- if (exp->ex_Stor.st_Label < 0) {
- exp->ex_Stor.st_Label = -exp->ex_Stor.st_Label;
- exp->ex_Stor.st_Flags= 0;
- exp->ex_Stor.st_Type = ST_RelLabel;
- } else
- #endif
- {
- exp->ex_Stor.st_Flags= SF_LEA;
- exp->ex_Stor.st_Type = ST_RelLabel;
-
- if (ConstCode)
- exp->ex_Stor.st_Flags |= SF_CODE; /* in code section */
- }
- exp->ex_Stor.st_Size = PTR_SIZE;
- exp->ex_Stor.st_Offset = 0;
- }
- }
-
- void
- GenFltConst(pexp)
- Exp **pexp;
- {
- Exp *exp = *pexp;
-
- if (GenPass == 0) {
- Assert(exp->ex_Type);
- exp->ex_Flags |= EF_CRES;
- AllocFltConstStor(&exp->ex_Stor, exp->ex_Stor.st_FltConst, exp->ex_Stor.st_FltLen, exp->ex_Type);
- } else {
- exp->ex_Stor.st_Size = exp->ex_Type->Size;
-
- if (exp->ex_Flags & EF_COND) {
- exp->ex_Flags |= EF_CONDACK;
- if (exp->ex_Cond >= 0 && FltIsZero(exp, exp->ex_Stor.st_FltConst, exp->ex_Stor.st_FltLen))
- asm_branch(exp->ex_LabelT);
- if (exp->ex_Cond < 0 && !FltIsZero(exp, exp->ex_Stor.st_FltConst, exp->ex_Stor.st_FltLen))
- asm_branch(exp->ex_LabelF);
- }
-
- #ifdef NOTDEF
- /*
- * Convert an fp string constant into a memory constant and change
- * the storage type to label.
- */
-
- asm_data_mask(0); XXX
- asm_fltconst(&exp->ex_Stor, 1);
- asm_code_mask(0); XXX
- #endif
- }
- }
-
- /*
- * left side is ex_Var, a variable. Right side is ex_Symbol, a symbol.
- *
- * For array references we return the effective address of a pointer to
- * the array. BUT, if the array is passed as an argument we return only
- * a pointer to the array (since we can't get the eff.addr without generating
- * code).
- *
- * If a register variable we have a problem... The register could have been
- * forced and reused.
- *
- * __dynamic variables are automatically indirected through.
- */
-
- void
- GenVarRef(pexp)
- Exp **pexp;
- {
- Exp *exp = *pexp;
- Var *var = exp->ex_Var;
-
- if (GenPass == 0) {
- Assert(var);
-
- /*
- * dynamic variables are automatically indirected
- */
-
- #ifdef DYNAMIC
- if ((var->Flags & TF_DYNAMIC) && (exp->ex_Flags & EF_DYNAMIC) == 0) {
- exp->ex_Flags |= EF_DYNAMIC;
- InsertNot(pexp);
- exp = *pexp;
- exp->ex_Func = GenInd;
- (*exp->ex_Func)(pexp);
- return;
- }
- #endif
- exp->ex_Type = var->Type;
- exp->ex_Flags |= EF_CRES;
- exp->ex_Stor.st_Flags |= SF_VAR;
-
- if (var->Type->Id == TID_PROC)
- exp->ex_Type = TypeToPtrType(var->Type);
-
- if (var->Type->Id == TID_ARY && (var->Flags & VF_ARG))
- exp->ex_Type = TypeToPtrType(exp->ex_Type->SubType);
- } else {
- exp->ex_Stor = var->var_Stor;
- exp->ex_Stor.st_Flags |= SF_VAR;
-
- /*
- * check for a change in type. In order to modify this
- * expression's type without adding another expression node
- * the type's Id and size may not be changed (see InsertCast())
- */
-
- if (exp->ex_Type->Flags & TF_UNSIGNED)
- exp->ex_Stor.st_Flags |= SF_UNSIGNED;
- else
- exp->ex_Stor.st_Flags &= ~SF_UNSIGNED;
-
- if (var->Type->Id == TID_PROC) {
- if (var->var_Stor.st_Type == ST_RelName) {
- if (var->var_Stor.st_Name->Len == 6 && strncmp(var->var_Stor.st_Name->Name, "alloca", 6) == 0) {
- yerror(exp->ex_LexIdx, EERROR_ALLOCA);
- }
- if (var->var_Stor.st_Name->Len == 12 && strncmp(var->var_Stor.st_Name->Name, "_dice_alloca", 12) == 0) {
- ForceLinkFlag = 1;
- puts("; FORCE LINK");
- }
- }
- }
-
- /*
- * XXX - handling of registerized procedure name access
- * ('@' or '_') -mR option. XXX
- */
-
- #ifdef NOTDEF
-
- if (var->Type->Flags & TF_REGCALLOK) {
- if (RegCallOpt > 2 || (exp->ex_Flags & EF_DIRECT)) {
- /* printf("VARFLAG = %08lx\n", var->Flags); */
- if (IsRegCall(var->Flags)) {
- exp->ex_Stor.st_Flags |= SF_REGARGS;
- var->var_Stor.st_Flags |= SF_REGARGSUSED;
- }
- }
- }
- #endif
- if (var->Type->Flags & TF_REGCALL) {
- exp->ex_Stor.st_Flags |= SF_REGARGS;
- var->var_Stor.st_Flags |= SF_REGARGSUSED;
- }
-
-
- if (exp->ex_Stor.st_Type == 0)
- {
- yerror(exp->ex_LexIdx, EERROR_ILLEGAL_ASSIGNMENT);
- dbprintf(("var %s has no type!", SymToString(var->Sym)));
- Assert(0);
- }
-
- #ifdef NOTDEF
- if ((var->Flags & TF_EXTERN) && !(var->Flags & VF_DECLD)) {
- AddExternList(var);
- var->Flags |= VF_DECLD;
- }
- #endif
- if ((var->Flags & VF_DECLD) == 0) {
- if (var->Flags & TF_EXTERN)
- AddExternList(var);
- var->Flags |= VF_DECLD;
- }
-
- exp->ex_Stor.st_Size = exp->ex_Type->Size;
- if (var->Type->Id == TID_ARY) {
- if (var->Flags & VF_ARG) {
- exp->ex_Stor.st_Size = PTR_SIZE;
- } else {
- exp->ex_Stor.st_Flags |= SF_LEA;
- exp->ex_Stor.st_Size = PTR_SIZE;
- }
- }
- if (var->Type->Id == TID_PROC) {
- exp->ex_Stor.st_Flags |= SF_LEA; /* ptr to procedure */
- exp->ex_Stor.st_Size = PTR_SIZE;
- }
- }
- }
-
- /*
- * right side of call is an expression list rather than just an expression
- */
-
- void
- GenCall(pexp)
- Exp **pexp;
- {
- Exp *exp = *pexp;
- Exp *e1;
-
- if (GenPass == 0) {
- Exp **pe = &exp->ex_ExpR;
- Exp *e2;
- Exp *en;
-
- CallLeft();
- e1 = exp->ex_ExpL;
-
- while ((e2 = *pe) != NULL) {
- en = e2->ex_Next;
-
- (*e2->ex_Func)(pe);
-
- (*pe)->ex_Next = en;
- pe = &(*pe)->ex_Next;
- }
- #ifdef NOTDEF
- if (e1->ex_Stor.st_Type == ST_IntConst) {
- e1->ex_Stor.st_IntConst = !e1->ex_Stor.st_IntConst;
- *pexp = e1;
- return;
- }
- #endif
- {
- Type *t = e1->ex_Type;
-
- if (t->Id == TID_PTR)
- t = t->SubType;
-
- if (t->Id != TID_PROC) {
- yerror(e1->ex_LexIdx, EERROR_LHS_NOT_PROCEDURE);
- exp->ex_Type = &LongType;
- } else {
- exp->ex_Type = t->SubType; /* return type of proc */
- if (ProtoOnlyOpt && !(t->Flags & TF_PROTOTYPE))
- yerror(e1->ex_LexIdx, EERROR_UNPROTOTYPED_CALL);
- }
-
- GenCastArgs(t, exp, &exp->ex_ExpR);
- }
- exp->ex_Flags |= EF_CALL;
- GenFlagCallMade();
- } else {
- Stor *calls;
- Stor ts;
- short struct_ret;
- PragNode *pragma_call;
- Type *type = exp->ex_ExpL->ex_Type;
- char prgno[16]; /* pragma register ordering */
-
- if (type->Id == TID_PTR)
- type = type->SubType;
- Assert(type->Id == TID_PROC);
-
- e1 = exp->ex_ExpL;
- e1->ex_Flags |= EF_DIRECT;
-
- if (type->SubType->Id == TID_STRUCT || type->SubType->Id == TID_UNION)
- struct_ret = 1;
- else
- struct_ret = 0;
-
- if (exp->ex_ExpL->ex_Token == TokVarRef) {
- pragma_call = TestPragmaCall(exp->ex_ExpL->ex_Var, prgno);
- if (pragma_call && (type->Flags & TF_PROTOTYPE) == 0)
- yerror(exp->ex_LexIdx, EERROR_PROTO_REQUIRED_INLINE);
- } else {
- pragma_call = NULL;
- }
-
- if (pragma_call == NULL && (type->Flags & TF_REGCALL) == 0) {
- /*
- * STACK BASED CALL
- */
-
- short autop;
- long bytes;
-
- if (exp->ex_ExpR)
- bytes = GenPushArgs(exp->ex_ExpR);
- else
- bytes = 0;
-
- if ((exp->ex_Flags & EF_STACK) && struct_ret == 0) {
- exp->ex_Flags |= EF_STACKACK;
- exp->ex_Flags |= EF_RNU;
- autop = 1;
- } else {
- CreateUnaryResultStorage(exp, 0);
- autop = 0;
- }
-
- /*
- * Calculate call ea
- */
-
- CallLeft();
- e1 = exp->ex_ExpL;
- calls = &e1->ex_Stor;
-
- FreeStorage(&e1->ex_Stor);
-
- if (e1->ex_Type->Id == TID_PTR) {
- asm_getind(exp, e1->ex_Type, &e1->ex_Stor, &ts, -1, -1, 0);
- calls = &ts;
- FreeStorage(calls);
- }
-
- /*
- * stack call, must clear SF_REGARGS so '_' label is used
- */
-
- calls->st_Flags &= ~SF_REGARGS;
-
- if (exp->ex_Flags & EF_RNU)
- asm_call(exp, calls, exp->ex_Type, NULL, bytes, autop);
- else
- asm_call(exp, calls, exp->ex_Type, &exp->ex_Stor, bytes, autop);
-
- } else {
- /*
- * REGISTERIZED PROCEDURE CALL
- *
- * (1) calculate those arguments whos register destinations
- * do not conflict directly to the appropriate
- * register destinations
- *
- * (2) calculate the call address to a temporary
- *
- * (3) calculate those arguments whos register destinations
- * conflict, calculate them to non-conflicting temporary
- * variables.
- *
- * (4) save registers in the conflict zone
- *
- * (5) move remaining temporary results to actual registers
- *
- * (6) make call (do not assign result storage yet)
- *
- * (7) restore registers in the conflict zone, move result
- * storage elsewhere if it conflicts.
- *
- * (8) assign result storage
- */
-
- ulong conMask; /* conflict mask */
- ulong ignMask = -1; /* conflict save/restore mask */
- char argno[16]; /* procedure call register ordering */
- char actno[16]; /* actual regs for initial arg load */
- char scReg[5]; /* scratch registers saved */
- Stor res; /* result storage backing store */
- short resBack = 0; /* backing store active */
-
- scReg[0] = -1;
-
- /*
- * Generate result storage
- */
-
- CreateUnaryResultStorage(exp, 0);
-
- /*
- * Generate a register list and a conflict mask. This call
- * also sets the 'used' bit for the registers if it is not
- * already set.
- */
-
- conMask = RegCallOrder(type, argno, (pragma_call) ? prgno : NULL);
-
- dbprintf((";conMask = %08lx\n", conMask));
-
- /*
- * Generate arguments for those bits that do not conflict with
- * anything. The storage for these arguments will be locked.
- */
-
- GenRegArgs(exp->ex_ExpR, argno, actno, ~conMask, scReg, 0);
-
- /*
- * If the result storage conflicts with a register and is
- * not register-direct then we have to assign it to temporary
- * storage first.
- *
- * If it is register direct (& conflict) then we do not have
- * to assign it to temporary storage but must clear the
- * conflict bit so we do not restore over our result
- *
- * Note that since the storage for the result in the case of
- * a hard conflict is allocated after non-conflicting registers
- * are allocated it will thus not conflict with anything and
- * therefore not get restored over.
- */
-
- if (RegisterMaskConflict(&exp->ex_Stor, conMask)) {
- if (exp->ex_Stor.st_Type == ST_Reg) {
- ignMask = ~(1 << exp->ex_Stor.st_RegNo);
- } else {
- res = exp->ex_Stor;
- resBack = 1;
- AllocAnyRegister(&exp->ex_Stor, exp->ex_Type, NULL);
- }
- }
-
- /*
- * Generate arguments for those bits that conflict with
- * something. Results will be written to other temporary
- * registers or pushed onto the stack, and locked.
- */
-
- GenRegArgs(exp->ex_ExpR, argno, actno, conMask & ignMask, scReg, 1);
-
- /*
- * Generate call address to non-conflicting temporary
- *
- * If the call is a __libcall we offset it by the first
- * argument.
- *
- * Otheriwse,
- *
- * If the call address is a pointer we have to resolve it,
- * if the register conflicts with an argument we have to
- * copy it to another register.
- *
- * We special case TID_PTR where the pointer is the same as
- * the first argument in the call (the library base variable)
- *
- * XXX call address not guarenteed to be in non-conflicting
- * register!
- */
-
- InMaskPush(e1, scReg);
-
- CallLeft();
- e1 = exp->ex_ExpL;
- calls = &e1->ex_Stor;
-
- if (pragma_call) {
- AllocRegisterAbs(&ts, RB_A6, 4);
- ts.st_Type = ST_RelReg;
- ts.st_Offset = -pragma_call->pn_Offset;
- calls = &ts;
- } else if (RegisterMaskConflict(calls, conMask)) {
- AllocAddrRegister(&ts);
- if (e1->ex_Type->Id == TID_PTR)
- asm_move(exp, calls, &ts);
- else
- asm_lea(exp, calls, 0, &ts);
- FreeStorage(&ts);
- asm_getind(exp, &LongPtrType, &ts, &ts, -1, -1, 0);
- FreeStorage(calls);
- calls = &ts;
- } else if (e1->ex_Type->Id == TID_PTR) {
- asm_getind(e1, e1->ex_Type, &e1->ex_Stor, &ts, -1, -1, 0);
- FreeStorage(calls);
- calls = &ts;
- }
-
- /*
- * Optimize result storage if it was a conflicting register,
- * as well as prevent restoring over the result. We force
- * the argument into the conflicted register (and do this last
- * so there will be no further access to the now destructed
- * register)
- */
-
- if (ignMask != -1)
- GenRegArgs(exp->ex_ExpR, argno, actno, ~ignMask, scReg, -1);
-
- /*
- * While calculating arguments or the call address if any
- * subexpression had made a call we had to (and did) save
- * any allocated scratch registers we need. We have to
- * restore them here.
- */
-
- InMaskPop(scReg);
-
- /*
- * Save conflicting variables and move already-generated
- * arguments associated with said conflicts into their
- * proper registers. (note: since this survives the call
- * we cannot save conflicts into scratch registers)
- *
- * We do not save any variable that represents the result
- * storage as this would cause the result storage to be
- * overwritten on restore.
- */
-
- SaveCopyConflictsRegArgs(exp->ex_ExpR, argno, actno, conMask & ignMask, 0);
-
- /*
- * Make the call
- */
-
- FreeStorage(calls);
- if (exp->ex_Flags & EF_RNU)
- asm_call(exp, calls, exp->ex_Type, NULL, 0, 2);
- else
- asm_call(exp, calls, exp->ex_Type, &exp->ex_Stor, 0, 2);
-
- /*
- * Restore conflicted variables, either from other registers
- * or off the stack.
- */
-
- SaveCopyConflictsRegArgs(exp->ex_ExpR, argno, actno, conMask & ignMask, 1);
-
- FreeRegArgs(exp->ex_ExpR, actno);
-
- /*
- * If the result would have conflicted we created a temporary
- * for it and now must store it back after all other registers
- * have been restored.
- */
-
- if (resBack) {
- FreeStorage(&exp->ex_Stor);
- asm_move(exp, &exp->ex_Stor, &res);
- exp->ex_Stor = res;
- }
- }
- }
- }
-
- /*
- * Generate arguments to registers. If tmpOk is 1 then argument
- * will be generated to a temporary if the associated register is
- * not available.
- *
- * Must handle case where char or short quantity is placed in an
- * address register
- *
- * Must handle pragma case where extra register in argno/actno is the
- * base register
- *
- * tmpOk
- * -1 no, force register to be used even if a conflict
- * 0 no, register must be free
- * 1 yes
- */
-
- void
- GenRegArgs(
- Exp *exp,
- char *argno,
- char *actno,
- ulong mask,
- char *scReg,
- short tmpOk
- ) {
- Stor t;
-
- for (; exp; exp = exp->ex_Next, ++argno, ++actno) {
- short rno = -1;
-
- /*
- * Do only the requested arguments
- */
-
- if ((mask & (1 << *argno)) == 0)
- continue;
-
- /*printf(";GenRegArgs tmp = %d argno = %d RegAlloc=%08lx RegLocked=%08lx RegUsed=%08lx\n", tmpOk, *argno, RegAlloc, RegLocked, RegUsed);*/
-
- /*
- * Attempt to optimize destination register for the subexpression,
- * but cannot do this if the subexpression contains a call
- * (screws up register save & restore). Also, due to __dp calls
- * D0 must be the last to be resolved. XXX ???
- *
- * Do not optimize ADDRESS REG destination if exptype size is not 4,
- * don't think expression generation routines can handle it.
- */
-
- if (*argno < RB_ADDR || exp->ex_Type->Size == 4) {
- if ((exp->ex_Flags & (EF_CRES|EF_ASSEQ)) == 0 && !(exp->ex_Flags & EF_CALL)) {
- if (tmpOk < 0)
- rno = AllocRegisterAbs(&t, *argno, exp->ex_Type->Size);
- else
- rno = AttemptAllocRegisterAbs(&t, *argno, exp->ex_Type->Size);
- exp->ex_Stor = t;
- exp->ex_Flags |= EF_PRES;
- }
- }
-
- InMaskPush(exp, scReg);
- (*exp->ex_Func)(&exp);
-
- if ((exp->ex_Flags & EF_PRES) == 0) {
- if (((1 << *argno) & REGSCRATCH) == 0 && exp->ex_Stor.st_Type == ST_Reg && exp->ex_Stor.st_RegNo == *argno && exp->ex_Type->Size == exp->ex_Stor.st_Size) {
- rno = *argno;
- AllocRegisterAbs(&t, rno, exp->ex_Stor.st_Size);
- } else {
- FreeStorage(&exp->ex_Stor);
- if (tmpOk < 0)
- rno = AllocRegisterAbs(&t, *argno, exp->ex_Type->Size);
- else
- rno = AttemptAllocRegisterAbs(&t, *argno, exp->ex_Type->Size);
-
- /*
- * Hack the destination register size. Set to 2 if short
- * or char type. Even though we are moving 'garbage'
- * into the high bits of the register, the type sized bits
- * will be correct.
- */
-
- if (rno >= RB_ADDR && exp->ex_Type->Size < 4) {
- exp->ex_Stor.st_Size = 2;
- t.st_Size = 2;
- }
- asm_move_cast(exp, &exp->ex_Stor, &t);
- }
- }
- *actno = rno;
-
- /*printf(";GenRegArgs actual = %d\n", rno);*/
-
- if ((1 << rno) & REGSCRATCH) {
- short i;
- for (i = 0; i < 4 && (short)(scReg[i] & 0x7F) != rno; ++i) {
- if (scReg[i] == -1) {
- scReg[i] = rno;
- scReg[i+1] = -1;
- break;
- }
- }
- }
-
- if (tmpOk <= 0 && rno != *argno)
- {
- dbprintf(("rno alloc failed %d/%d (%d)\n", rno, *argno, tmpOk));
- Assert(0);
- }
- }
- }
-
- /*
- * We have to save any scratch registers we have in use if the expression
- * we are about to evaluate contains a call. We do not re-save registers
- * which have already been saved.
- */
-
- void
- InMaskPush(exp, scReg)
- Exp *exp;
- char *scReg;
- {
- if (exp->ex_Flags & EF_CALL) {
- short i;
- char c;
-
- for (i = 0; i < 4 && (c = scReg[i]) != -1; ++i) {
- if ((c & 0x80) == 0) {
- scReg[i] |= 0x80;
- asm_push_mask(1 << c);
- }
- }
- }
- }
-
- /*
- * Before completing the call we have to pop any registers we had saved,
- * and must be sure to pop them in the correct order.
- */
-
- void
- InMaskPop(scReg)
- char *scReg;
- {
- short i;
- char c;
-
- for (i = 0; i < 4 && scReg[i] != -1; ++i)
- ;
- for (--i; i >= 0; --i) {
- if ((c = scReg[i]) & 0x80) {
- asm_pop_mask(1 << (c & 0x7F));
- }
- }
- }
-
- /*
- * Save conflicting registers while simultaniously moving the stored
- * temporary into the conflicting register spot. The stored temporaries
- * do not conflict with any of these registers.
- *
- * Only those registers represented by <mask> might conflict and are
- * considered. If possible, we EXG the temporaries with the real
- * registers. Otherwise we store the real registers on the stack and
- * MOVE from the temporaries. On restore the opposite action occurs
- *
- * Since the register(s) are already allocated we can allocate/free
- * without actually freeing them up.
- */
-
- void
- SaveCopyConflictsRegArgs(
- Exp *expBase,
- char *argno,
- char *actno,
- ulong mask,
- short restore
- ) {
- Stor t;
- Stor a;
- Exp *exp;
- long regMask;
- short i;
-
- for (i = regMask = 0, exp = expBase; exp; exp = exp->ex_Next, ++i) {
- if (mask & (1 << argno[i])) {
- if ((1 << actno[i]) & REGSCRATCH) {
- if (restore == 0)
- regMask |= 1 << argno[i];
- }
- }
- }
- asm_push_mask(regMask);
-
- for (i = regMask = 0, exp = expBase; exp; exp = exp->ex_Next, ++i) {
- if (mask & (1 << argno[i])) {
- AllocRegisterAbs(&t, argno[i], exp->ex_Stor.st_Size);
- AllocRegisterAbs(&a, actno[i], exp->ex_Stor.st_Size);
-
- /*
- * AllocRegisterAbs() forces the size of an address register
- * to 4 currently, XXX this is a hack
- */
-
- if (exp->ex_Stor.st_Size < 4) {
- t.st_Size = 2;
- a.st_Size = 2;
- }
-
- if ((1 << actno[i]) & REGSCRATCH) {
- if (restore) {
- regMask |= 1 << argno[i];
- } else {
- asm_move(exp, &a, &t);
- }
- } else {
- asm_exg(&a, &t);
- }
- FreeRegister(&a);
- FreeRegister(&t);
- }
- }
- asm_pop_mask(regMask);
- }
-
- /*
- * Free registers allocated for the call arguments, clean up. Note
- * that if we do not properly free arguments a software error, such
- * as 'rno alloc failed' from the level above may occur.
- */
-
- void
- FreeRegArgs(exp, actno)
- Exp *exp;
- char *actno;
- {
- Stor t;
-
- for (; exp; exp = exp->ex_Next, ++actno) {
- AllocRegisterAbs(&t, *actno, exp->ex_Stor.st_Size);
- FreeStorage(&t);
- FreeStorage(&t);
- }
- }
-
- Local long
- GenPushArgs(exp)
- Exp *exp;
- {
- long bytes;
-
- if (exp->ex_Next)
- bytes = GenPushArgs(exp->ex_Next);
- else
- bytes = 0;
- return(bytes + PushArgExp(exp));
- }
-
- int
- PushArgExp(exp)
- Exp *exp;
- {
- exp->ex_Flags |= EF_STACK;
- (*exp->ex_Func)(&exp);
-
- if (exp->ex_Flags & EF_STACKACK) {
- return(asm_stackbytes(exp->ex_Type));
- } else {
- FreeStorage(&exp->ex_Stor);
- return(asm_push(exp, exp->ex_Type, &exp->ex_Stor));
- }
- }
-
- void
- GenCastArgs(type, cexp, pexp)
- Type *type;
- Exp *cexp;
- Exp **pexp;
- {
- Exp *exp = *pexp;
- short i;
-
- /*
- * if type->Args < 0 it is not a prototype, but that is ok the way
- * our loop works.
- */
-
- dbprintf((";%d args, flags = %08lx\n", type->Args, type->Flags));
-
- for (i = 0; i < type->Args; ++i) {
- Type *vtype;
- if (exp == NULL || (exp->ex_Flags & EF_SPECIAL)) {
- yerror(cexp->ex_LexIdx, EWARN_TOO_FEW_PARAMETERS);
- break;
- }
-
- vtype = ActualPassType(type, type->Vars[i]->Type, 0);
-
- dbprintf((";arg %d size=%ld argsize=%ld use=%ld\n", i, exp->ex_Type->Size, type->Vars[i]->Type->Size, vtype->Size));
-
- if (exp->ex_Type != vtype) {
- if (exp->ex_Type->Id == TID_INT && (vtype->Id == TID_INT || (exp->ex_Stor.st_Type == ST_IntConst && exp->ex_Stor.st_IntConst == 0))) {
- InsertCast(pexp, vtype);
- } else if (CheckConversion(exp, exp->ex_Type, vtype)) {
- InsertCast(pexp, vtype); /* exp no longer valid */
- }
- }
-
- exp = *pexp;
- pexp = &exp->ex_Next;
- exp = *pexp;
- }
- {
- Exp *ex;
-
- for (ex = exp; ex && (ex->ex_Flags & EF_SPECIAL); ex = ex->ex_Next)
- ;
- if (ex && (type->Flags & TF_DOTDOTDOT) == 0 && type->Args >= 0)
- yerror(ex->ex_LexIdx, EWARN_TOO_MANY_PARAMETERS);
- }
-
- while (exp) {
- Type *vtype = ActualPassType(type, exp->ex_Type, 1);
-
- if (exp->ex_Type != vtype)
- InsertCast(pexp, vtype); /* exp no longer valid */
- exp = *pexp;
- pexp = &exp->ex_Next;
- exp = *pexp;
- }
- }
-
- void
- GenPosInc(pexp)
- Exp **pexp;
- {
- Exp *exp = *pexp;
- Exp *e1;
-
- CallLeft();
- e1 = exp->ex_ExpL;
-
- if (GenPass == 0) {
- #ifdef NOTDEF
- if (e1->ex_Stor.st_Type == ST_IntConst) {
- e1->ex_Stor.st_IntConst = !e1->ex_Stor.st_IntConst;
- *pexp = e1;
- return;
- }
- #endif
- exp->ex_Type = e1->ex_Type;
- exp->ex_Flags |= e1->ex_Flags & EF_CALL;
-
- if (e1->ex_Token == TokVarRef)
- e1->ex_Var->RegFlags |= RF_MODIFIED;
- if (e1->ex_Type->Id == TID_FLT) {
- exp->ex_Flags |= EF_CALL;
- GenFlagCallMade();
- }
- } else {
- Stor con;
-
- if (exp->ex_Type->Id == TID_FLT)
- AllocFltConstStor(&con, "1", 1, exp->ex_Type);
- else
- AllocConstStor(&con, AutoIncDecSize(e1), e1->ex_Type);
-
- CreateUnaryResultStorage(exp, 0);
- if ((exp->ex_Flags & EF_RNU) == 0) {
- exp->ex_Stor.st_Flags |= e1->ex_Stor.st_Flags & SF_UNSIGNED;
- asm_move(exp, &e1->ex_Stor, &exp->ex_Stor);
- }
- FreeStorage(&e1->ex_Stor);
- if (exp->ex_Type->Id == TID_FLT)
- asm_fpadd(exp, exp->ex_Type, &con, &e1->ex_Stor, &e1->ex_Stor);
- else
- asm_add(exp, &con, &e1->ex_Stor, &e1->ex_Stor);
- }
- }
-
- void
- GenPosDec(pexp)
- Exp **pexp;
- {
- Exp *exp = *pexp;
- Exp *e1;
-
- CallLeft();
- e1 = exp->ex_ExpL;
-
- if (GenPass == 0) {
- #ifdef NOTDEF
- if (e1->ex_Stor.st_Type == ST_IntConst) {
- e1->ex_Stor.st_IntConst = !e1->ex_Stor.st_IntConst;
- *pexp = e1;
- return;
- }
- #endif
- exp->ex_Flags |= e1->ex_Flags & EF_CALL;
- exp->ex_Type = e1->ex_Type;
-
- if (e1->ex_Token == TokVarRef)
- e1->ex_Var->RegFlags |= RF_MODIFIED;
- if (e1->ex_Type->Id == TID_FLT) {
- exp->ex_Flags |= EF_CALL;
- GenFlagCallMade();
- }
- } else {
- Stor con;
-
- if (exp->ex_Type->Id == TID_FLT)
- AllocFltConstStor(&con, "1", 1, exp->ex_Type);
- else
- AllocConstStor(&con, AutoIncDecSize(e1), e1->ex_Type);
-
- CreateUnaryResultStorage(exp, 0);
- if ((exp->ex_Flags & EF_RNU) == 0) {
- exp->ex_Stor.st_Flags |= e1->ex_Stor.st_Flags & SF_UNSIGNED;
- asm_move(exp, &e1->ex_Stor, &exp->ex_Stor);
- }
- FreeStorage(&e1->ex_Stor);
- if (exp->ex_Type->Id == TID_FLT)
- asm_fpsub(exp, exp->ex_Type, &e1->ex_Stor, &con, &e1->ex_Stor);
- else
- asm_sub(exp, &e1->ex_Stor, &con, &e1->ex_Stor);
- }
- }
-
- /*
- * For Ind/Elm, exp->ex_Sym (right side is a symbol)
- *
- * BITFIELD NOTE: Only asm_getind() is guarenteed to leave the
- * st_BOffset and st_BSize fields alone.
- */
-
- void
- GenStructInd(pexp)
- Exp **pexp;
- {
- Exp *exp = *pexp;
- Exp *e1;
- int bfo;
-
- CallLeft();
- e1 = exp->ex_ExpL;
-
- if (GenPass == 0) {
- if (e1->ex_Type->Id != TID_PTR && e1->ex_Type->Id != TID_ARY) {
- yerror(e1->ex_LexIdx, EERROR_INDIRECTION_NOT_PTR);
- exp->ex_Type = &LongType;
- return;
- }
- exp->ex_Offset = FindStructUnionElm(e1->ex_Type->SubType, exp, &bfo);
- if (exp->ex_Type == NULL)
- exp->ex_Type = &LongType;
- if (exp->ex_Type->Id == TID_BITFIELD) {
- BitFieldResultType(pexp, bfo);
- exp = *pexp;
- e1 = exp->ex_ExpL;
- } else {
- exp->ex_Stor.st_BOffset = -1;
- exp->ex_Stor.st_BSize = -1;
- }
- /*exp->ex_Flags |= EF_CRES;*/
- exp->ex_Flags |= e1->ex_Flags & EF_CALL;
-
- /*
- * constant pointer
- */
-
- if (exp->ex_Type->Id != TID_BITFIELD && e1->ex_Stor.st_Type == ST_IntConst) {
- if (exp->ex_Type->Id == TID_ARY) {
- e1->ex_Stor.st_Type = ST_IntConst;
- e1->ex_Stor.st_Size = PTR_SIZE;
- e1->ex_Stor.st_IntConst = e1->ex_Stor.st_IntConst + exp->ex_Offset;
- e1->ex_Stor.st_Flags |= SF_LEA | SF_UNSIGNED;
- } else {
- e1->ex_Stor.st_Type = ST_PtrConst;
- e1->ex_Stor.st_Size = exp->ex_Type->Size;
- e1->ex_Stor.st_Offset = e1->ex_Stor.st_IntConst + exp->ex_Offset;
- e1->ex_Stor.st_Flags &= ~SF_LEA;
- }
- e1->ex_Type = exp->ex_Type;
- *pexp = e1;
- }
- } else {
- Stor con;
- Stor t;
-
- FreeStorage(&e1->ex_Stor);
-
- if ((exp->ex_Flags & EF_RNU) == 0) {
- AllocConstStor(&con, exp->ex_Offset, &LongType);
- asm_getindex(exp, e1->ex_Type, &e1->ex_Stor, &con, 1, &t, 1, 0);
- FreeStorage(&t);
- if (!(exp->ex_Stor.st_Flags & SF_BITFIELD))
- exp->ex_Stor.st_BSize = -1;
- asm_getind(exp, TypeToPtrType(exp->ex_Type), &t, &exp->ex_Stor, exp->ex_Stor.st_BOffset, exp->ex_Stor.st_BSize, AutoResultStorage(exp));
-
- /*
- if (exp->ex_Stor.st_Flags & SF_BITFIELD) {
- BitFieldResultExp(exp);
- }
- */
- }
- }
- }
-
- void
- GenStructElm(pexp)
- Exp **pexp;
- {
- Exp *exp = *pexp;
- Exp *e1;
- int bfo; /* for bitfields */
-
- CallLeft();
- e1 = exp->ex_ExpL;
-
- if (GenPass == 0) {
- {
- Type *t = e1->ex_Type;
-
- if (t->Id != TID_STRUCT && t->Id != TID_UNION)
- yerror(e1->ex_LexIdx, EERROR_NOT_STRUCT_UNION);
-
- exp->ex_Offset = FindStructUnionElm(t, exp, &bfo);
- }
- if (exp->ex_Type == NULL)
- exp->ex_Type = &LongType;
- if (exp->ex_Type->Id == TID_BITFIELD) {
- BitFieldResultType(pexp, bfo);
- exp = *pexp;
- e1 = exp->ex_ExpL;
- } else {
- exp->ex_Stor.st_BOffset = -1;
- exp->ex_Stor.st_BSize = -1;
- }
- /*exp->ex_Flags |= EF_CRES;*/
- exp->ex_Flags |= e1->ex_Flags & EF_CALL;
-
- /*
- * constant pointer
- */
-
- if (exp->ex_Type->Id != TID_BITFIELD && e1->ex_Stor.st_Type == ST_IntConst) {
- if (exp->ex_Type->Id == TID_ARY) {
- e1->ex_Stor.st_Type = ST_IntConst;
- e1->ex_Stor.st_Size = PTR_SIZE;
- e1->ex_Stor.st_IntConst = e1->ex_Stor.st_IntConst + exp->ex_Offset;
- e1->ex_Stor.st_Flags |= SF_LEA | SF_UNSIGNED;
- } else {
- e1->ex_Stor.st_Type = ST_PtrConst;
- e1->ex_Stor.st_Size = exp->ex_Type->Size;
- e1->ex_Stor.st_Offset = e1->ex_Stor.st_IntConst + exp->ex_Offset;
- e1->ex_Stor.st_Flags &= ~SF_LEA;
- }
- e1->ex_Type = exp->ex_Type;
- *pexp = e1;
- }
- } else {
- Stor con;
- Stor t;
- Stor u;
-
- FreeStorage(&e1->ex_Stor);
-
- if ((exp->ex_Flags & EF_RNU) == 0) {
- AllocConstStor(&con, exp->ex_Offset, &LongType);
-
- asm_getlea(exp, &e1->ex_Stor, &t);
- FreeStorage(&t);
-
- asm_getindex(exp, TypeToPtrType(e1->ex_Type), &t, &con, 1, &u, 1, 0);
- FreeStorage(&u);
-
- if (!(exp->ex_Stor.st_Flags & SF_BITFIELD))
- exp->ex_Stor.st_BSize = -1;
- asm_getind(exp, TypeToPtrType(exp->ex_Type), &u, &exp->ex_Stor, exp->ex_Stor.st_BOffset, exp->ex_Stor.st_BSize, AutoResultStorage(exp));
- /*
- if (exp->ex_Stor.st_Flags & SF_BITFIELD) {
- BitFieldResultExp(exp);
- }
- */
- }
- }
- }
-
- /*
- * Handle bitfield result types. If this isn't the LHS of a straight
- * assignment, the type is coerced into an integer.
- */
-
- void
- BitFieldResultType(pexp, bfo)
- Exp **pexp;
- int bfo;
- {
- Exp *exp = *pexp;
-
- exp->ex_Stor.st_BOffset = bfo;
- exp->ex_Stor.st_BSize = exp->ex_Type->Size;
- exp->ex_Stor.st_Flags |= SF_BITFIELD;
-
- /*
- * bit field return type is an integer unless lhs of
- * assignment.
- */
-
- if ((exp->ex_Flags & (EF_LHSASSIGN|EF_COND)) == 0) {
- InsertNot(pexp);
- exp = *pexp;
- if (exp->ex_ExpL->ex_Flags & EF_LHSASSEQ)
- exp->ex_Flags |= EF_LHSASSEQ;
- exp->ex_Func = GenBFExt;
- exp->ex_Token = TokBFExt; /* FOR +=, -=, etc... */
-
- if (exp->ex_ExpL->ex_Type->Flags & TF_UNSIGNED)
- exp->ex_Type = &ULongType;
- else
- exp->ex_Type = &LongType;
- }
- }
-
- #ifdef NOTDEF
- /*
- * BitFieldResultExp
- */
-
- void
- BitFieldResultExp(exp)
- Exp *exp;
- {
- if (exp->ex_Flags & EF_LHSASSIGN)
- return;
- if (exp->ex_Flags & EF_COND) /* can handle some conds.*/
- return;
- /*
- * but otherwise must store into integer
- */
- if (exp->ex_Stor.st_Flags & SF_BITFIELD) {
- Stor st = exp->ex_Stor;
-
- FreeStorage(&exp->ex_Stor);
- CreateUnaryResultStorage(exp, 0);
- asm_bfext(exp, &st, &exp->ex_Stor);
- }
- }
- #endif
-
- void
- GenBFExt(pexp)
- Exp **pexp;
- {
- Exp *e1;
- Exp *exp = *pexp;
-
- CallLeft();
- e1 = exp->ex_ExpL;
-
- if (GenPass == 0) {
- ;
- } else {
- Assert(e1->ex_Stor.st_Flags & SF_BITFIELD);
- if ((exp->ex_Flags & EF_LHSASSEQ) == 0)
- FreeStorage(&e1->ex_Stor);
- CreateUnaryResultStorage(exp, 0);
- asm_bfext(exp, &e1->ex_Stor, &exp->ex_Stor);
- }
- }
-
-
- void
- GenArray(pexp)
- Exp **pexp;
- {
- Exp *exp = *pexp;
- Exp *e1;
- Exp *e2;
-
- CallLeft();
- EnsureReturnStorageLeft();
- CallRight();
- e1 = exp->ex_ExpL;
- e2 = exp->ex_ExpR;
-
- if (GenPass == 0) {
- Type *t1 = e1->ex_Type;
-
- exp->ex_Flags |= /* EF_CRES |*/ ((e1->ex_Flags | e2->ex_Flags) & EF_CALL);
- if (t1->Id == TID_PTR || t1->Id == TID_ARY) {
- exp->ex_Type = t1->SubType;
-
- if (e2->ex_Stor.st_Type != ST_IntConst) {
- if (asm_mul_requires_call(t1->SubType->Size)) {
- exp->ex_Flags |= EF_CALL;
- GenFlagCallMade();
- }
- if (e2->ex_Type->Id != TID_INT)
- yerror(e2->ex_LexIdx, EERROR_EXPECTED_INT_TYPE);
- }
- return;
- }
- yerror(e1->ex_LexIdx, EERROR_INDIRECTION_NOT_PTR);
- exp->ex_Type = &VoidPtrType;
- } else {
- Stor t;
-
- FreeStorage(&e1->ex_Stor);
- FreeStorage(&e2->ex_Stor);
- if ((exp->ex_Flags & EF_RNU) == 0) {
- asm_getindex(exp, e1->ex_Type, &e1->ex_Stor, &e2->ex_Stor, exp->ex_Type->Size, &t, 1, 0);
- FreeStorage(&t);
- asm_getind(exp, e1->ex_Type, &t, &exp->ex_Stor, -1, -1, AutoResultStorage(exp));
- }
- }
- }
-
-
-